﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ValiVIN.Manufacturer
{
    internal class Infiniti : IVINManufacturer
    {
        //Example VIN: JNKCV51E53M018995

        private static readonly int _EARLIEST_Year = 1990;

        #region Singleton

        static readonly Infiniti _instance = new Infiniti();

        public static Infiniti Instance
        {
            get { return _instance; }
        }

        #endregion

        private void GetMiscellaneous(VINumber vin)
        {
            //A	Air Bag System
            //C	Air Bag System
            //D	Driver & Front Passenger Air Bag  + 3 Point Seat Belt
            //E	 Driver and front passenger SRS air bags, SRS side air bags, SRS curtain air bag & 3 point manual seat belt
            //P	Passive Restraint System
            //Y	4 Wheel Drive
            string key = "Miscellaneous";
            string misc = string.Empty;
            string m = vin.VIN.Substring(7, 1);

            switch (m)
            {
                case "A":
                case "C":
                    misc = "Air Bag System";
                    break;
                case "D":
                    misc = "Driver & Front Passenger Air Bag  + 3 Point Seat Belt";
                    break;
                case "E":
                    misc = "Driver and front passenger SRS air bags, SRS side air bags, SRS curtain air bag & 3 point manual seat belt";
                    break;
                case "P":
                    misc = "Passive Restraint System";
                    break;
                case "Y":
                    misc = "4-Wheel Drive";
                    break;
            }

            if (!string.IsNullOrEmpty(misc))
            {
                vin.ManufacturerSpecifics[key] = misc;
            }
        }

        private void GetPlant(VINumber vin)
        {
            //T	Tochigi(J30, 1990-1993 Q45)
            //T	Oppama(M30, G20)
            //M	Tochigi(1994-1996 Q45)
            //M	Tochigi (G35, J30, M45, G37, FX, EX, M)
            //W	Kyushyu
            string plant = string.Empty;
            string p = vin.VIN.Substring(10, 1);
            string vl = vin.VIN.Substring(4, 2); //some plants depend on certain models

            switch (p)
            {
                case "T":
                    if (vl == "P0" || vl == "P1" || vl == "F1")
                    {
                        plant = "Oppama";
                    }
                    else
                    {
                        plant = "Tochigi";
                    }
                    break;
                case "M":
                    plant = "Tochigi";
                    break;
                case "W":
                    plant = "Kyushyu";
                    break;
            }

            vin.Plant = plant;
        }

        private void GetSerialNumber(VINumber vin)
        {
            //12 - 17
            string serialNum = vin.VIN.Substring(11, 6);
            vin.SerialNumber = serialNum;
        }

        private void GetBodyType(VINumber vin)
        {
            //1	4-Door Sedan (J30, Q45, G20, M45, I30)
            //4	2-Door Coupe (M30, G35)
            //5	4-Door Wagon
            //6	2-Door Convertible (M30)
            //8	Wagon
            string key = "Body Type";
            string body = string.Empty;
            string b = vin.VIN.Substring(6, 1);

            switch (b)
            {
                case "1":
                    body = "4-Door Sedan";
                    break;
                case "4":
                    body = "2-Door Coupe";
                    break;
                case "5":
                    body = "4-Door Wagon";
                    break;
                case "6":
                    body = "2-Door Convertible";
                    break;
                case "8":
                    body = "Wagon";
                    break;
            }

            if (!string.IsNullOrEmpty(body))
            {
                vin.ManufacturerSpecifics[key] = body;
            }
        }

        private void GetVehicleLine(VINumber vin)
        {
            //G0	1990-1996 Q45(G50)
            //Y3	1997-2001 Q45(Y33)
            //F0	2002-2006 Q45(F50)
            //Y2	1993-1997 J30(Y32)
            //S1	2009-2010 FX35, FX50(S51)
            //S0	2004-2008 FX35, FX45(S50)
            //R0	QX4(R50)
            //V6	G37 Coupe, G37 Sedan (V36)
            //V5	G35 Coupe, G35 Sedan (V35)
            //A3	2000-2001	I30(A33), 2002- I35(A33)
            //A2	1996-1999	I30(A32)
            //F1	M30(F31)
            //Y4	2003 M45(Y34)
            //P0	1991-1996 G20(P10)
            //P1	1999-2002	G20(P11)
            string key = "Vehicle Line";
            string line = string.Empty;
            string v = vin.VIN.Substring(4, 2);

            switch (v)
            {
                case "G0":
                    line = "Q45 (G50)";
                    break;
                case "Y3":
                    line = "Q45 (Y33)";
                    break;
                case "F0":
                    line = "Q45 (F50)";
                    break;
                case "Y2":
                    line = "J30 (Y32)";
                    break;
                case "S1":
                    line = "FX35, FX50 (S51)";
                    break;
                case "S0":
                    line = "FX35, FX45 (S50)";
                    break;
                case "R0":
                    line = "QX4 (R50)";
                    break;
                case "V6":
                    line = "G37";
                    break;
                case "V5":
                    line = "G35";
                    break;
                case "A3":
                    line = "I30, I35 (A33)";
                    break;
                case "A2":
                    line = "I30 (A33)";
                    break;
                case "F1":
                    line = "M30 (F31)";
                    break;
                case "Y4":
                    line = "M45 (Y34)";
                    break;
                case "P0":
                    line = "G20 (P10)";
                    break;
                case "P1":
                    line = "G20 (P11)";
                    break;
            }

            if (!string.IsNullOrEmpty(line))
            {
                vin.ManufacturerSpecifics[key] = line;
            }
        }

        private void GetEngineType(VINumber vin)
        {
            //A	VG30D(J30), VK45DE(M45)
            //B	KA24DE; SR20DE
            //C	SR20DE(G20), VQ35DE(I30), VQ35DE (G35)
            //D	KA24DE; QG18DE, VQ35DE
            //E	VE30DE; GA16DE
            //F	KA24E
            //H	VG30E (M30)
            //M	KA24DE; VG33ER
            //N	VH45DE(1990-1996 Q45)
            //R	VG30DE (QX4)
            //S	KA24E
            //T	VG33E
            string engine = string.Empty;
            string e = vin.VIN.Substring(3, 1);
            string v = vin.VIN.Substring(4, 2);

            switch (e)
            {
                case "A":
                    if (v == "Y2")
                    {
                        engine = "VG30D";
                    }
                    else
                    {
                        engine = "VK45DE";
                    }
                    break;
                case "B":
                    if (vin.Year < 1998)
                    {
                        engine = "KA24DE";
                    }
                    else
                    {
                        engine = "SR20DE";
                    }
                    break;
                case "C":
                    if (v == "V5")
                    {
                        engine = "VQ35DE";
                    }
                    else if (v == "P0" || v == "P1")
                    {
                        engine = "SR20DE";
                    }
                    else
                    {
                        engine = "VQ35DE";
                    }
                    break;
                case "D":
                    if (vin.Year >= 2002)
                    {
                        engine = "VQ35DE";
                    }
                    else if (vin.Year < 1998)
                    {
                        engine = "KA24DE";
                    }
                    else
                    {
                        engine = "QG18DE";
                    }
                    break;
                case "E":
                //E	VE30DE; GA16DE --VE30DE was only used in the Nissan Maxima 92-94. Will assume infinity is GA16DE only
                    engine = "GA16DE";
                    break;
                case "F":
                    engine = "KA24E";
                    break;
                case "H":
                    engine = "VG30E";
                    break;
                case "M":
                //M	KA24DE; VG33ER
                //N	VH45DE(1990-1996 Q45)
                    if (vin.Year < 1998)
                    {
                        engine = "KA24DE";
                    }
                    else
                    {
                        engine = "VG33ER";
                    }
                    break;
                case "N":
                    if (vin.Year1 <= 1996 && vin.Year >= 1990)
                    {
                        engine = "VH45DE";
                    }
                    break;
                case "R":
                    engine = "VG30DE";
                    break;
                case "S":
                    engine = "KA24E";
                    break;
                case "T":
                    engine = "VG33E";
                    break;
            }

            vin.EngineType = engine;
            GetEngineSpecifics(vin);
        }

        private void GetEngineSpecifics(VINumber vin)
        {
            if (string.IsNullOrEmpty(vin.EngineType) || vin.EngineType.Length < 5) { return; }

            //Displacement
            string displacement = vin.EngineType.Substring(2, 2) + " Liters";
            vin.ManufacturerSpecifics["Displacement"] = displacement;

            //Valve Train
            string vt = vin.EngineType.Substring(4, 1);
            if (vt == "D")
            {
                vin.ManufacturerSpecifics["Valve Train"] = "DOHC";
            }
            else if (vt == "V")
            {
                vin.ManufacturerSpecifics["Valve Train"] = "Variable Valve Lift (VVL) plus DOHC";
            }

            //Fuel Delivery
            //E	Multiport Fuel Injection
            //I	Throttle Body Fuel Injection
            //D	Direct Injection
            string f = vin.EngineType.Substring(5, 1);
            if (f == "E")
            {
                vin.ManufacturerSpecifics["Fuel Delivery"] = "Multiport Fuel Injection";
            }
            else if (f == "I")
            {
                vin.ManufacturerSpecifics["Fuel Delivery"] = "Throttle Body Fuel Injection";
            }
            else if (f == "D")
            {
                vin.ManufacturerSpecifics["Fuel Delivery"] = "Direct Injection";
            }

            //
        }

        #region IVINManufacturer Members

        public bool Decode(VINumber vin)
        {
            CheckYear(vin);
            GetEngineType(vin);
            GetVehicleLine(vin);
            GetBodyType(vin);
            GetMiscellaneous(vin);
            GetPlant(vin);
            GetSerialNumber(vin);
            return true;
        }

        private void CheckYear(VINumber vin)
        {
            if (vin.Year1 < _EARLIEST_Year)
            {
                vin.Year1 = vin.Year2;
                vin.Year2 = 0;
            }
        }

        public string ManufacturerName(string vin)
        {
            //JNK	Japan-Infiniti
            //JNR	Japan Multi-Purpose
            string s = vin.Substring(0, 3);
            if (s == "JNR") { return "Japan Multi-Purpose"; }
            return "Infiniti";
        }

        #endregion
    }
}
